package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

// 17 | SliceHeader：slice 如何高效处理数据？
func main() {

	ss := []string{"靖哥哥", "996"}
	ss = append(ss, "财富自由", "高富帅")
	fmt.Println(ss)
	fmt.Println("切片ss的长度为", len(ss), "容量为", cap(ss))

	ss = append(ss, "迎娶白富美", "走向人生巅峰")
	fmt.Println("切片ss的长度为", len(ss), "容量为", cap(ss))
	fmt.Println(ss)

	a1 := [2]string{"靖哥哥", "996"}
	fmt.Printf("函数main数组指针: %p\n", &a1)
	arrayF(a1)

	// 打印出s1和s2的Data值，是一样的
	s1 := a1[0:1]
	fmt.Println((*reflect.SliceHeader)(unsafe.Pointer(&s1)).Data)
	sliceF(s1)

	s2 := a1[:]
	fmt.Println((*reflect.SliceHeader)(unsafe.Pointer(&s2)).Data)

	// 注意：多个切片共用一个底层数组虽然可以减少内存占用，但是如果有一个切片修改内部的元素，其他切片也会受影响。
	// 所以在切片作为参数在函数间传递的时候要小心，尽可能不要修改原切片内的元素。
	// 小提示：SliceHeader 三个字段的类型分别是 uintptr、int 和 int，在 64 位的机器上，
	// 这三个字段最多也就是 int64 类型，一个 int64 占 8 个字节，三个 int64 占 24 个字节内存。

	sh1 := (*slice)(unsafe.Pointer(&s1))
	fmt.Println(sh1.Date, sh1.Len, sh1.Cap)

	s := "靖哥哥"
	fmt.Printf("s的内存地址：%d\n", (*reflect.SliceHeader)(unsafe.Pointer(&s)).Data)

	b := []byte(s)
	fmt.Printf("b的内存地址：%d\n", (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data)

	s3 := string(b)
	fmt.Printf("s3的内存地址：%d\n", (*reflect.SliceHeader)(unsafe.Pointer(&s3)).Data)

	fmt.Println(s, string(b), s3)

	s4 := *(*string)(unsafe.Pointer(&b))
	fmt.Printf("s4的内存地址：%d\n", (*reflect.SliceHeader)(unsafe.Pointer(&s4)).Data)

	sh := (*reflect.SliceHeader)(unsafe.Pointer(&s))
	sh.Cap = sh.Len
	b1 := *(*[]byte)(unsafe.Pointer(sh))
	fmt.Printf("b1的内存地址：%d\n", (*reflect.SliceHeader)(unsafe.Pointer(&b1)).Data)
}

type slice struct {
	Date uintptr
	Len  int
	Cap  int
}

func arrayF(a [2]string) {
	fmt.Printf("函数arrayF数组指针: %p\n", &a)
}

func sliceF(s []string) {
	fmt.Printf("函数sliceF Data: %d\n\n", (*reflect.SliceHeader)(unsafe.Pointer(&s)).Data)
}
